/**
 * @file exampleSolverEqu.cpp
 * @author shikang999@126.com
 * @brief 这个例子主要演示如何进行非线性拟合
 * @version 0.1
 * @date 2025-06-25
 * 
 * @copyright Copyright (c) 2025
 * 
 */

#include "SolverFun.h"
#include "BaseFun.h"
#include "HelpFun.h"
#include "DumpLog.h"

#include <sstream>
#include <iomanip>

using namespace Solver;
class Fun : public BaseFun
{
public:
    Fun(std::size_t dim):   BaseFun(dim,
                            FunType_E::Nohting_E, 
                            DifficultyLevel_E::Nothing_E,
                            1,
                            "",
                            "")
    {
        constexpr value_t a = 10.89;
        constexpr value_t b = 1234.567;
        constexpr value_t c = -3124.67;
        for (std::size_t i = 0; i != 100; ++i)
        {
            //产生测试数据 y = a * sin(x/10) + log(b + x) + 15 * std::cos(x / c)
            //时间测试数据通过其它方式产生
            x.push_back(i);
            y.push_back(a * std::sin(x.back() / 10) + std::log(b + x.back()) + 15 * std::cos(x.back() / c));
        }
    }

    ~Fun()
    {

    }

    //拟合表达式: y = a * sin(x/10) + log(b + x) + 15 * std::cos(x / c), 其中a,b,c为待优化系数
    value_t calcFun(const VectorXd_t &param)
    {
        value_t f(0), s;
        value_t a = param[0];
        value_t b = param[1];
        value_t c = param[2];
        for (std::size_t i = 0; i != x.size(); ++i)
        {
            s = a * std::sin(x[i] / 10) + std::log(b + x[i]) + 15 * std::cos(x[i] / c) - y[i];
            if (std::isnan(s))
            {
                return std::numeric_limits<value_t>::max();
            }

            f += s * s;
        }

        return f;
    }

private:
    vecValue_t x;
    vecValue_t y;
};

int main()
{
    //1.设置需要测试的函数
    std::shared_ptr<BaseFun> fun = std::make_shared<Fun>(3);//这里3表示拟合变量维度,即a,b,c
    
    //2.设置需要测试的求解器
    auto solver = SolverFun::SolverFun::getSolver(SolverType_E::SWO_E);

    //3.设置迭代条件
    Solver::value_t minErr = 0;     //迭代终止目标,当目标函数值小于此值时停止迭代
    std::size_t iterSum    = 10000; //最大迭代次数

    //4.设置变量范围
    Solver::value_t minVar = -10000; //变量下限
    Solver::value_t maxVar = 10000;  //变量上限

    //5.设置种群数量
    std::size_t popNum = 90;

    //6.求解
    {
        //6.1 设置基本参数
        solver->setFun(fun);
        solver->setVarRange(minVar, maxVar, fun->getDim());
        solver->getCondition().limitError = minErr;
        solver->getCondition().limitIter  = iterSum;
        solver->setPrintNum(50);//间隔50次打印一次结果

        //6.2 求解
        solver->solve(popNum);
        solver->waitExit();

        //6.3 获取结果
        auto res = solver->getResult();

        //6.4 打印
        std::ostringstream ss;
        ss << std::setprecision(16);
        ss  << "------------------------------------------\n"
            << "\n最终目标值:"    << solver->getResult()->y                      << "\n"
            << "最终优化值:[\n" << Help::printVecValue(solver->getResult()->x) << "]\n"
            << "------------------------------------------\n";
        
        LogInfo(ss.str());
    }

    return 0;
}